#include"StdTcp.h"
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"StdThread.h"
#include"DoubleLinkList.h"

struct Client
{
    char name[20];
    int sock;
};

typedef struct Client C;
C* createC(const char *name,int sock)
{
    C *c=(C*)malloc(sizeof(C));
    if(c==NULL)
    {
        perror("C:");
        return NULL;
    }
    strcpy(c->name,name);
    c->sock=sock;
    return c;
}

void FreeC(C *c)
{
    free(c);
}

DLlist ClientList;    //用双向链表创建一个客户端的列表

struct Message
{
    int flag;
    char fromName[20];
    char toName[20];
    char content[1024];
};
typedef struct Message Msg;
void *thread_handle(void *arg)
{     //由于void *arg传入的是一个万能指针类型的套接字，而sock要的是一个整型，所以将arg强制转换成一个(int *)整型指针型
    int sock=*((int *)arg);    //再对指针取值就能获取到套接字的值了
    while(1)
    {
        Msg m;
        TcpServerRecv(sock,&m,sizeof(m));    //将接收到的客户端的套接字里的信息存在m里
        switch(m.flag)
        {
            case 1:    //当flag为1时,表示有新客户端连接,调用InsertTail函数将客户端信息添加到ClientList中                
                InsertTail(&ClientList,createC(m.fromName,sock));
                break;
            case 2:  //当flag为2时,将消息转发给特定客户端.遍历ClientList,查找匹配目标客户端名称的套接字,并使用TcpServerSend函数将消息发送给该客户端。
                struct Node *TravelPoint=ClientList.head;
                while(TravelPoint!=NULL)
                {
                    C *c=(C*)TravelPoint->data;
                    if(strcmp(c->name,m.toName)==0)
                    {
                        TcpServerSend(c->sock,&m,sizeof(m));
                        break;
                    }
                    TravelPoint=TravelPoint->next;
                }                
            default:
                break;
        }
    }
}

int main(int argc, char *argv[])
{
    if(argc!=3)
    {
        printf("invalid numbers!\n");
        return -1;
    }
    
    InitDLinkList(&ClientList);     //初始化存储客户端列表的这个双向链表

    TcpS *s=InitTcpServer(argv[1],atoi(argv[2]));
    
    int acceptSock;   //TcpServerAccept函数返回一个客户端1与服务器建立连接的新的套接字,别的客户端就可以通过这个新的套接字与客户端1建立连接
    while((acceptSock=TcpServerAccept(s))>0)   //为每个客户端连接创建一个独立的线程
    {
        thread *t=InitThread(thread_handle,&acceptSock);
        DetachThread(t);
    }
    return 0;
}